from Tkinter import *
from math import sin
from math import cos

#Iguala puntos. Recibe coordenadas en 3D y el punto objetivo.
def iguala(x,y,z,obj):
	if obj == 'A':
		Punto3D[0][0]=x
		Punto3D[0][1]=y
		Punto3D[0][2]=z
	if obj == 'B':
		Punto3D[1][0]=x
		Punto3D[1][1]=y
		Punto3D[1][2]=z
	if obj == 'C':
		Punto3D[2][0]=x
		Punto3D[2][1]=y
		Punto3D[2][2]=z
	if obj == 'D':
		Punto3D[3][0]=x
		Punto3D[3][1]=y
		Punto3D[3][2]=z
		
#Convierte la coordenada 3D a 2D. Recibe la coordenada en 3D (A,B,C o D).
def coordenadas_pantalla(x,y,z):
	Punto2D[0]=(x)+(200)
	Punto2D[1]=(200)-(y)

#Rota la esfera en un punto (x,y,z). Recibe coordenada en 3D, cantidad de giro, punto objetivo y punto de rotacion.
def rotacion(x,y,z,giro,obj,rotacion):
	if obj == 'A':
		if rotacion == 'x':
			Punto3D[0][0]=x
			Punto3D[0][1]=y*cos(giro*3.14159/180)+z*sin(giro*3.14159/180)
			Punto3D[0][2]=z*cos(giro*3.14159/180)-y*sin(giro*3.14159/180)
		if rotacion == 'y':
			Punto3D[0][0]=x*cos(giro*3.14159/180)+z*sin(giro*3.14159/180)
			Punto3D[0][1]=y
			Punto3D[0][2]=z*cos(giro*3.14159/180)-x*sin(giro*3.14159/180)
		if rotacion == 'z':
			Punto3D[0][0]=x*cos(giro*3.14159/180)+y*sin(giro*3.14159/180)
			Punto3D[0][1]=y*cos(giro*3.14159/180)-x*sin(giro*3.14159/180)
			Punto3D[0][2]=z	
	if obj == 'B':
		if rotacion == 'x':
			Punto3D[1][0]=x
			Punto3D[1][1]=y*cos(giro*3.14159/180)+z*sin(giro*3.14159/180)
			Punto3D[1][2]=z*cos(giro*3.14159/180)-y*sin(giro*3.14159/180)
		if rotacion == 'y':
			Punto3D[1][0]=x*cos(giro*3.14159/180)+z*sin(giro*3.14159/180)
			Punto3D[1][1]=y
			Punto3D[1][2]=z*cos(giro*3.14159/180)-x*sin(giro*3.14159/180)
		if rotacion == 'z':
			Punto3D[1][0]=x*cos(giro*3.14159/180)+y*sin(giro*3.14159/180)
			Punto3D[1][1]=y*cos(giro*3.14159/180)-x*sin(giro*3.14159/180)
			Punto3D[1][2]=z	
	if obj == 'C':
		if rotacion == 'x':
			Punto3D[2][0]=x
			Punto3D[2][1]=y*cos(giro*3.14159/180)+z*sin(giro*3.14159/180)
			Punto3D[2][2]=z*cos(giro*3.14159/180)-y*sin(giro*3.14159/180)
		if rotacion == 'y':
			Punto3D[2][0]=x*cos(giro*3.14159/180)+z*sin(giro*3.14159/180)
			Punto3D[2][1]=y
			Punto3D[2][2]=z*cos(giro*3.14159/180)-x*sin(giro*3.14159/180)
		if rotacion == 'z':
			Punto3D[2][0]=x*cos(giro*3.14159/180)+y*sin(giro*3.14159/180)
			Punto3D[2][1]=y*cos(giro*3.14159/180)-x*sin(giro*3.14159/180)
			Punto3D[2][2]=z	
	if obj == 'D':
		if rotacion == 'x':
			Punto3D[3][0]=x
			Punto3D[3][1]=y*cos(giro*3.14159/180)+z*sin(giro*3.14159/180)
			Punto3D[3][2]=z*cos(giro*3.14159/180)-y*sin(giro*3.14159/180)
		if rotacion == 'y':
			Punto3D[3][0]=x*cos(giro*3.14159/180)+z*sin(giro*3.14159/180)
			Punto3D[3][1]=y
			Punto3D[3][2]=z*cos(giro*3.14159/180)-x*sin(giro*3.14159/180)
		if rotacion == 'z':
			Punto3D[3][0]=x*cos(giro*3.14159/180)+y*sin(giro*3.14159/180)
			Punto3D[3][1]=y*cos(giro*3.14159/180)-x*sin(giro*3.14159/180)
			Punto3D[3][2]=z

#Traslada la esfera en el plano. Recibe coordenada 3D, traslacion (en x,y,z), punto objetivo.
def traslacion(x,y,z,Tx,Ty,Tz,obj):
	if obj == 'A':
		Punto3D[0][0]=Punto3D[0][0]+Tx
		Punto3D[0][1]=Punto3D[0][1]+Ty
		Punto3D[0][2]=Punto3D[0][2]+Tz
	if obj == 'B':
		Punto3D[1][0]=Punto3D[1][0]+Tx
		Punto3D[1][1]=Punto3D[1][1]+Ty
		Punto3D[1][2]=Punto3D[1][2]+Tz
	if obj == 'C':
		Punto3D[2][0]=Punto3D[2][0]+Tx
		Punto3D[2][1]=Punto3D[2][1]+Ty
		Punto3D[2][2]=Punto3D[2][2]+Tz
	if obj == 'D':
		Punto3D[3][0]=Punto3D[3][0]+Tx
		Punto3D[3][1]=Punto3D[3][1]+Ty
		Punto3D[3][2]=Punto3D[3][2]+Tz

#Funcion principal del programa.
def principal():
	n=20			#numero de iteraciones para la poliedrizacion.
	radio=100		#radio de la esfera.
	inc=3.14159/n*2		#incremento.
	latitud=3.14159/2	#latitud.
	longitud=0		#longitud.
	ra=0;
	rb=0;
	A=[0,0,0]
	B=[0,0,0]
	C=[0,0,0]
	D=[0,0,0]
	Centro=[0,0,0]
	X=0
	Y=0
	giroX=0
	giroY=0
	giroZ=0
	global Punto3D
	Punto3D=[A,B,C,D,Centro]
	global Punto2D
	Punto2D=[X,Y]
	Punto3D[0][0]=Punto3D[4][0]
	Punto3D[0][1]=Punto3D[4][1]+radio
	Punto3D[0][2]=Punto3D[4][2]
	traslacion(Punto3D[0][0],Punto3D[0][1],Punto3D[0][2],-Punto3D[4][0],-Punto3D[4][1],-Punto3D[4][2],'A')
	canvas = Canvas(width=500, height=500, bg='white')
	canvas.pack(expand=YES, fill=BOTH)
	for i in range(n/2):
		iguala(Punto3D[0][0], Punto3D[0][1], Punto3D[0][2], 'B')
		latitud=latitud-inc
		longitud=0
		Punto3D[0][1]=radio*sin(latitud)
		Punto3D[0][2]=radio*cos(latitud)
		rb=ra
		ra=Punto3D[0][2]
		for j in range(n):
			longitud=longitud+inc
			iguala(Punto3D[0][0], Punto3D[0][1], Punto3D[0][2], 'C')
			iguala(Punto3D[1][0], Punto3D[1][1], Punto3D[1][2], 'D')
			Punto3D[0][0]=ra*sin(longitud)
			Punto3D[0][2]=ra*cos(longitud)
			Punto3D[1][0]=rb*sin(longitud)
			Punto3D[1][2]=rb*cos(longitud)
			#Trasladamos A
			traslacion(Punto3D[0][0],Punto3D[0][1],Punto3D[0][2],Punto3D[4][0],Punto3D[4][1],Punto3D[4][2],'A')
			#Rotamos A respecto a X
			rotacion(Punto3D[0][0],Punto3D[0][1],Punto3D[0][2],giroX,'A','x')
			#Trasladamos B
			traslacion(Punto3D[1][0],Punto3D[1][1],Punto3D[1][2],Punto3D[4][0],Punto3D[4][1],Punto3D[4][2],'B')
			#Rotamos B respecto a X
			rotacion(Punto3D[1][0],Punto3D[1][1],Punto3D[1][2],giroX,'B','x')
			#Trasladamos C
			traslacion(Punto3D[2][0],Punto3D[2][1],Punto3D[2][2],Punto3D[4][0],Punto3D[4][1],Punto3D[4][2],'C')
			#Rotamos C respecto a X
			rotacion(Punto3D[2][0],Punto3D[2][1],Punto3D[2][2],giroX,'C','x')
			#Trasladamos D
			traslacion(Punto3D[3][0],Punto3D[3][1],Punto3D[3][2],Punto3D[4][0],Punto3D[4][1],Punto3D[4][2],'D')
			#Rotamos D respecto a X
			rotacion(Punto3D[3][0],Punto3D[3][1],Punto3D[3][2],giroX,'D','x')
			coordenadas_pantalla(Punto3D[0][0], Punto3D[0][1], Punto3D[0][2])
			Punto2Dx = Punto2D[0]
			Punto2Dy = Punto2D[1]
			coordenadas_pantalla(Punto3D[1][0], Punto3D[1][1], Punto3D[1][2])
			canvas.create_line(Punto2Dx, Punto2Dy, Punto2D[0], Punto2D[1]) 		# A -> B
			Punto2Dx = Punto2D[0]
			Punto2Dy = Punto2D[1]
			coordenadas_pantalla(Punto3D[3][0], Punto3D[3][1], Punto3D[3][2])		
			canvas.create_line(Punto2Dx, Punto2Dy, Punto2D[0], Punto2D[1])		# B -> D
			Punto2Dx = Punto2D[0]
			Punto2Dy = Punto2D[1]
			coordenadas_pantalla(Punto3D[2][0], Punto3D[2][1], Punto3D[2][2])
			canvas.create_line(Punto2Dx, Punto2Dy, Punto2D[0], Punto2D[1]) 		# D -> C
			Punto2Dx = Punto2D[0]
			Punto2Dy = Punto2D[1]
			coordenadas_pantalla(Punto3D[0][0], Punto3D[0][1], Punto3D[0][2])
			canvas.create_line(Punto2Dx, Punto2Dy, Punto2D[0], Punto2D[1]) 		# C -> A
			rotacion(Punto3D[0][0],Punto3D[0][1],Punto3D[0][2],-giroX,'A','x')
			traslacion(Punto3D[0][0],Punto3D[0][1],Punto3D[0][2],-Punto3D[4][0],-Punto3D[4][1],-Punto3D[4][2],'A')
			rotacion(Punto3D[1][0],Punto3D[1][1],Punto3D[1][2],-giroX,'B','x')
			traslacion(Punto3D[1][0],Punto3D[1][1],Punto3D[1][2],-Punto3D[4][0],-Punto3D[4][1],-Punto3D[4][2],'B')
			rotacion(Punto3D[2][0],Punto3D[2][1],Punto3D[2][2],-giroX,'C','x')
			traslacion(Punto3D[2][0],Punto3D[2][1],Punto3D[2][2],-Punto3D[4][0],-Punto3D[4][1],-Punto3D[4][2],'C')
			rotacion(Punto3D[3][0],Punto3D[3][1],Punto3D[3][2],-giroX,'D','x')
			traslacion(Punto3D[3][0],Punto3D[3][1],Punto3D[3][2],-Punto3D[4][0],-Punto3D[4][1],-Punto3D[4][2],'D')
	mainloop()
	

if __name__ == '__main__': principal()
	
	
	
	
